<?php

class BackupForm extends CModel {

    public $fileName;
    public $fileType;
    public $fileCharset;
    protected $_items = array();
    public $fileCreateTime;
    public $fileSize;
    public $dir = 'backup';
    public $selectImport;
    public $filePath;
    public $backup_and_download = 1;
    public $maxSize = 2; //最大备份文件
    public $backup_name;
    public $tableSpace = ";\r\n"; //分隔符

    public function getRoot() {
        return Yii::app()->basePath . DIRECTORY_SEPARATOR . $this->dir;
    }

    public function rules() {
        return array(
            array('selectImport', 'required')
        );
    }

    public function attributeLabels() {
        return array(
            'backup_title' => Yii::t('default', '数据库备份'),
            'backup_name' => Yii::t('default', '备份名称'),
            'selectImport' => Yii::t('default', '选择备份的资料'),
            'backup_path' => Yii::t('default', '保存路径'),
            'backup_create_time' => Yii::t('default', '备份时间'),
            'backup_import_time' => Yii::t('default', '最近还原'),
            'backup_file_size' => Yii::t('default', '文件大小'),
            'backup_create_user' => Yii::t('default', '备份者'),
            'backup_create_ip' => Yii::t('default', '备份者Ip'),
            'fileCharset' => Yii::t('default', '文件字符集'),
            'fileName' => Yii::t('default', '文件名称'),
            'fileType' => Yii::t('default', '类型'),
            'fileCreateTime' => Yii::t('default', '创建时间'),
            'backup_and_download' => Yii::t('default', '备份并且下载')
        );
    }

    /**
     * 读取目录下面所有文件
     * @return type
     * @throws Exception 
     */
    public function getFiles() {

        $path = $this->getRoot();
        if (stripos($path, '../') === false) {
            if (is_dir($path) === false) {
                if (!@mkdir($path, 0777, true)) {
                    Yii::log('无法创建备份文件目录' . $this->getRoot(), 'error', __CLASS__);
                    throw new Exception('无法创建备份文件目录' . $this->getRoot());
                }
            }

            $files = scandir($path);

            foreach ($files as $file) {
                if ($file != '.' && $file != '..') {
                    $data = array();
                    $filename = $this->getRoot() . DIRECTORY_SEPARATOR . $file;
                    if (is_dir($filename)) {
                        $data['filePath'] = base64_encode($file);
                    } else {
                        $data['filePath'] = base64_encode(basename($this->getRoot()).DIRECTORY_SEPARATOR.$file);
                        
                    }
                    $data['fileName'] = CHtml::link($file, Yii::app()->createUrl('admin/backup/view', array('dir' => $data['filePath'])));
                    $data['fileCreateTime'] = date('Y-m-d H:i:s', filemtime($filename));
                    $data['fileType'] = filetype($filename);
                    $data['fileSize'] = filesize($filename);
                    $this->_items[] = $data;
                    //$this->getFiles($backupDir.DIRECTORY_SEPARATOR.$file);
                }
            }
            unset($files, $data);
            //print_r($this->_items);
        } else {
            Yii::log('目录包含非法字符' . $this->getRoot(), 'error', __CLASS__);
        }
        return $this->_items;
    }

    /**
     * 递归的删除一个目录或者文件，但是限制删除的文件只能在备份的目录内
     * @param type $filePath 
     */
    public function delete($filePath) {
        $filePath = str_replace('../', '', urldecode($filePath));
        $filename = $this->getRoot() . DIRECTORY_SEPARATOR . $filePath;

        if (is_dir($filename)) {
            if (is_writable($filename)) {
                $files = scandir($filename);

                foreach ($files as $file) {
                    $dir = $filename . DIRECTORY_SEPARATOR . $file;
                    if ($file != '.' && $file != '..') {
                        if (is_dir($dir)) {
                            $this->delete($filePath . DIRECTORY_SEPARATOR . $file);
                        } else {
                            if (unlink($dir) === false) {
                                Yii::log(Yii::t('log', '删除文件' . $dir . '失败'), 'error', __CLASS__);
                            }
                        }
                    }
                }
                if (rmdir($filename) === false) {
                    Yii::log(Yii::t('log', '删除目录' . $dir . '失败'), 'error', __CLASS__);
                }
            }
        } else {
            if (unlink($filename) === false) {
                Yii::log(Yii::t('log', '删除文件' . $filename . '失败'), 'error', __CLASS__);
            }
        }
    }

    public function getTableList() {
        $result = array();
        $result['all'] = Yii::t('default', '所有资料');
        $result['user'] = Yii::t('default', '用户资料');
        $result['video'] = Yii::t('default', '视频资料');
        $result['log'] = Yii::t('default', '日志资料');
        $result['config'] = Yii::t('default', '配置资料');

        return $result;
    }

    public function doExport() {

        $tables = array();
        if ($this->selectImport == 'user') { //备份用户资料
            $tables[] = 'admin';
            $tables[] = 'admin_group';
            $tables[] = 'user_log';
            $tables[] = 'user_player';
            $tables[] = 'usergroup';
            $tables[] = 'users';
        }
        if ($this->selectImport == 'video') { //备份用户资料
            $tables[] = 'video';
            $tables[] = 'video_categorys';
            $tables[] = 'video_files';
            $tables[] = 'user_player';
            $tables[] = 'video_introduction';
            $tables[] = 'video_region';
            $tables[] = 'video_servers';
            $tables[] = 'category';
            $tables[] = 'recomemnd';
        }
        if ($this->selectImport == 'log') {
            $tables[] = 'user_log';
            $tables[] = 'log';
        }
        if ($this->selectImport == 'config') {
            $tables[] = 'backup';
            $tables[] = 'config';
            $tables[] = 'extension';
            $tables[] = 'menu';
            $tables[] = 'site';
        }
        if ($this->selectImport == 'all') {
            $cmd = Yii::app()->db->createCommand("show tables");
            $result = $cmd->queryAll();
            foreach ($result as $table) {
                $name = end($table);
                $tables[] = substr($name, stripos($name, '_') + 1);
            }
        }
        $this->__exportData($tables);
        return true;
    }

    /**
     * 备份数据
     * @param array $tables 表名称
     * @return boolean 
     */
    private function __exportData(array $tables) {
        $dump = "";
        $db = Yii::app()->db;
        $type = $this->getTableList();
        $path = $this->getRoot() . DIRECTORY_SEPARATOR . $this->backup_name . '(' . $type[$this->selectImport] . ')';
        if (is_dir($path) == false) {
            if (is_dir($path) === false) {
                mkdir($path, 0777, true); //递归的创建目录
            }
        } else {
            $this->delete(basename($path)); //目录存在就删除
        }

        $i = 1;
        $filename = $path . DIRECTORY_SEPARATOR . $i . '.gz';
        $zp = gzopen($filename, 'w9');
        foreach ($tables as $table) {
            $sql = "SHOW CREATE TABLE " . $db->tablePrefix . $table;
            $cmd = $db->createCommand($sql);
            $dump.= end($cmd->query()->read()) . $this->tableSpace;
            $cmd = $db->createCommand("SELECT * FROM " . $db->tablePrefix . $table);
            $reader = $cmd->query();

            foreach ($reader as $row) {
                $values = array_values($row);
                //$values = array_map("addslashes", $values);
                $dump.="INSERT IGNORE INTO `" . $db->tablePrefix . $table . "` VALUES('" . implode(',\'', $values) . "')" . $this->tableSpace;
            }
            gzwrite($zp, $dump);
            $dump = '';
            $filesize = filesize($filename);
            if ($filesize > intval($this->maxSize) * 1024 * 1000 * 1000) {
                gzclose($zp);
                $i++;
                $filename = $path . DIRECTORY_SEPARATOR . $i . '.gz';
                $zp = gzopen($filename, 'w9');
            }
        }
        gzclose($zp);
    }

    public function attributeNames() {
        return array();
    }

    /**
     * 恢复目录或者文件备份
     * @param type $file 
     */
    public function import($file) {
        $filename = $this->getRoot() . DIRECTORY_SEPARATOR . $file;
        if (is_dir($filename)) { //如果是目录就恢复整个目录内的文件
            $files = scandir($filename);
            foreach ($files as $f) {
                if ($f != '.' && $f != '..') {
                    $this->_importFile($filename . DIRECTORY_SEPARATOR . $f);
                }
            }
        } else {
            $this->_importFile($filename);
        }
        return null;
    }

    private function _importFile($file) {
        $zp = gzopen($file, "r");
        $db = Yii::app()->db;
        if ($zp) {
            while (!gzeof($zp)) {
                $dump.= gzgets($zp);
            }
            gzclose($zp);
            $sqlArray = explode(";\r\n", $dump);
            foreach ($sqlArray as $sql) {
                try {
                    $type = substr($sql, 0, 6);
                    preg_match('/`(\w+)`/is', $sql, $tables);
                    $table = $tables[1];

                    if ($type == 'CREATE') {
                        $title = Yii::t('log',"创建表:%s" , $table);
                    } else {
                         $title = Yii::t('log', "插入%s数据 ", $table);
          
                    }
                    $sql = str_replace($table, $db->tablePrefix. substr($table, stripos($table, '_') + 1), $sql);
                    $cmd = $db->createCommand($sql);
                    $cmd->execute();
                    Yii::log($title." sccuess", 'error', __CLASS__);
                } catch (Exception $e) {
                    $err = $e->getMessage();
                    Yii::log($title." failed", 'error', __CLASS__);
                }
            }
        }
    }

}